@@ -62,6 +62,8 @@ module Agents |
||
| 62 | 62 |
which contain `key` and `text`. For _free\\_text_, the special configuration options are all optional, and are |
| 63 | 63 |
`default`, `min_length`, and `max_length`. |
| 64 | 64 |
|
| 65 |
+ By default, all answers are emitted in a single event. If you'd like separate events for each answer, set `separate_answers` to `true`. |
|
| 66 |
+ |
|
| 65 | 67 |
# Combining answers |
| 66 | 68 |
|
| 67 | 69 |
There are a couple of ways to combine HITs that have multiple `assignments`, all of which involve setting `combination_mode` at the top level. |
@@ -105,7 +107,7 @@ module Agents |
||
| 105 | 107 |
} |
| 106 | 108 |
} |
| 107 | 109 |
|
| 108 |
- Resulting events will have the original `answers`, as well as the `poll` results, and a field called `best_answer` that contains the best answer as determined by the poll. |
|
| 110 |
+ Resulting events will have the original `answers`, as well as the `poll` results, and a field called `best_answer` that contains the best answer as determined by the poll. (Note that `separate_answers` won't work when doing a poll.) |
|
| 109 | 111 |
|
| 110 | 112 |
# Other settings |
| 111 | 113 |
|
@@ -351,8 +353,18 @@ module Agents |
||
| 351 | 353 |
|
| 352 | 354 |
log "Poll HIT created with ID #{poll_hit.id} and URL #{poll_hit.url}. Original HIT: #{hit_id}", :inbound_event => inbound_event
|
| 353 | 355 |
else |
| 354 |
- event = create_event :payload => payload |
|
| 355 |
- log "Event emitted with answer(s)", :outbound_event => event, :inbound_event => inbound_event |
|
| 356 |
+ if options[:separate_answers] |
|
| 357 |
+ payload['answers'].each.with_index do |answer, index| |
|
| 358 |
+ sub_payload = payload.dup |
|
| 359 |
+ sub_payload.delete('answers')
|
|
| 360 |
+ sub_payload['answer'] = answer |
|
| 361 |
+ event = create_event :payload => sub_payload |
|
| 362 |
+ log "Event emitted with answer ##{index}", :outbound_event => event, :inbound_event => inbound_event
|
|
| 363 |
+ end |
|
| 364 |
+ else |
|
| 365 |
+ event = create_event :payload => payload |
|
| 366 |
+ log "Event emitted with answer(s)", :outbound_event => event, :inbound_event => inbound_event |
|
| 367 |
+ end |
|
| 356 | 368 |
end |
| 357 | 369 |
end |
| 358 | 370 |
|
@@ -345,30 +345,53 @@ describe Agents::HumanTaskAgent do |
||
| 345 | 345 |
@checker.memory['hits'].should == { "JH3132836336DHG" => { 'event_id' => @event.id } }
|
| 346 | 346 |
end |
| 347 | 347 |
|
| 348 |
- it "should create events when all assignments are ready" do |
|
| 349 |
- @checker.memory['hits'] = { "JH3132836336DHG" => { 'event_id' => @event.id } }
|
|
| 350 |
- mock(RTurk::GetReviewableHITs).create { mock!.hit_ids { %w[JH3132836336DHG JH39AA63836DHG JH39AA63836DH12345] } }
|
|
| 351 |
- assignments = [ |
|
| 352 |
- FakeAssignment.new(:status => "Submitted", :answers => {"sentiment"=>"neutral", "feedback"=>""}),
|
|
| 353 |
- FakeAssignment.new(:status => "Submitted", :answers => {"sentiment"=>"happy", "feedback"=>"Take 2"})
|
|
| 354 |
- ] |
|
| 355 |
- hit = FakeHit.new(:max_assignments => 2, :assignments => assignments) |
|
| 356 |
- hit.should_not be_disposed |
|
| 357 |
- mock(RTurk::Hit).new("JH3132836336DHG") { hit }
|
|
| 348 |
+ context "emitting events" do |
|
| 349 |
+ before do |
|
| 350 |
+ @checker.memory['hits'] = { "JH3132836336DHG" => { 'event_id' => @event.id } }
|
|
| 351 |
+ mock(RTurk::GetReviewableHITs).create { mock!.hit_ids { %w[JH3132836336DHG JH39AA63836DHG JH39AA63836DH12345] } }
|
|
| 352 |
+ @assignments = [ |
|
| 353 |
+ FakeAssignment.new(:status => "Submitted", :answers => {"sentiment"=>"neutral", "feedback"=>""}),
|
|
| 354 |
+ FakeAssignment.new(:status => "Submitted", :answers => {"sentiment"=>"happy", "feedback"=>"Take 2"})
|
|
| 355 |
+ ] |
|
| 356 |
+ @hit = FakeHit.new(:max_assignments => 2, :assignments => @assignments) |
|
| 357 |
+ @hit.should_not be_disposed |
|
| 358 |
+ mock(RTurk::Hit).new("JH3132836336DHG") { @hit }
|
|
| 359 |
+ end |
|
| 358 | 360 |
|
| 359 |
- lambda {
|
|
| 360 |
- @checker.send :review_hits |
|
| 361 |
- }.should change { Event.count }.by(1)
|
|
| 361 |
+ it "should create events when all assignments are ready" do |
|
| 362 |
+ lambda {
|
|
| 363 |
+ @checker.send :review_hits |
|
| 364 |
+ }.should change { Event.count }.by(1)
|
|
| 362 | 365 |
|
| 363 |
- assignments.all? {|a| a.approved == true }.should be_truthy
|
|
| 364 |
- hit.should be_disposed |
|
| 366 |
+ @assignments.all? {|a| a.approved == true }.should be_truthy
|
|
| 367 |
+ @hit.should be_disposed |
|
| 365 | 368 |
|
| 366 |
- @checker.events.last.payload['answers'].should == [ |
|
| 367 |
- {'sentiment' => "neutral", 'feedback' => ""},
|
|
| 368 |
- {'sentiment' => "happy", 'feedback' => "Take 2"}
|
|
| 369 |
- ] |
|
| 369 |
+ @checker.events.last.payload['answers'].should == [ |
|
| 370 |
+ {'sentiment' => "neutral", 'feedback' => ""},
|
|
| 371 |
+ {'sentiment' => "happy", 'feedback' => "Take 2"}
|
|
| 372 |
+ ] |
|
| 373 |
+ |
|
| 374 |
+ @checker.memory['hits'].should == {}
|
|
| 375 |
+ end |
|
| 376 |
+ |
|
| 377 |
+ it "should emit separate answers when options[:separate_answers] is true" do |
|
| 378 |
+ @checker.options[:separate_answers] = true |
|
| 370 | 379 |
|
| 371 |
- @checker.memory['hits'].should == {}
|
|
| 380 |
+ lambda {
|
|
| 381 |
+ @checker.send :review_hits |
|
| 382 |
+ }.should change { Event.count }.by(2)
|
|
| 383 |
+ |
|
| 384 |
+ @assignments.all? {|a| a.approved == true }.should be_truthy
|
|
| 385 |
+ @hit.should be_disposed |
|
| 386 |
+ |
|
| 387 |
+ event1, event2 = @checker.events.last(2) |
|
| 388 |
+ event1.payload.should_not have_key('answers')
|
|
| 389 |
+ event2.payload.should_not have_key('answers')
|
|
| 390 |
+ event1.payload['answer'].should == { 'sentiment' => "happy", 'feedback' => "Take 2" }
|
|
| 391 |
+ event2.payload['answer'].should == { 'sentiment' => "neutral", 'feedback' => "" }
|
|
| 392 |
+ |
|
| 393 |
+ @checker.memory['hits'].should == {}
|
|
| 394 |
+ end |
|
| 372 | 395 |
end |
| 373 | 396 |
|
| 374 | 397 |
describe "taking majority votes" do |